package netty.service;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

import java.util.concurrent.TimeUnit;

public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    /**
     * 读取数据
     * @param ctx: 上下文对象，其中包含 pipeline、channel...
     * @param msg: 客户端发送数据
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("服务器读取线程: " + Thread.currentThread().getName());
        System.out.println("ChannelHandlerContext: " + ctx);
        Channel channel = ctx.channel();
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("客户端: " + channel.remoteAddress() + " 发送消息: " + buf.toString(CharsetUtil.UTF_8));
        // 将耗时任务加入到 taskQueue 中进行处理
        channel.eventLoop().execute(() -> {
            try {
                Thread.sleep(5 * 1000);
                System.out.println("channel " + channel.hashCode() + "处理耗时任务完成...");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        // 添加定时任务
        channel.eventLoop().schedule(() -> {
            ctx.writeAndFlush(Unpooled.copiedBuffer("定时任务处理完成...", CharsetUtil.UTF_8));
            System.out.println("channel " + channel.hashCode() + "处理定时任务完成...");
        }, 10, TimeUnit.SECONDS);
    }

    /**
     * 读取数据完毕
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // 将数据写入到缓存中, 并刷新
        ctx.writeAndFlush(Unpooled.copiedBuffer("回复数据...", CharsetUtil.UTF_8));
    }

    /**
     * 处理异常, 并关闭通道
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println(cause.getMessage());
        ctx.close();
    }
}
